"""
编译 solidity 文件，并部署合约，以及将abi和部署地址写入和sol文件同名的py文件中
只适用于当前的sol文件中只有一个合约的情况。
"""

import json
import re
from web3 import Web3
from web3.middleware import geth_poa_middleware
from solcx import compile_source, set_solc_version

def camel_to_snake(name):
    s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
    return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()

set_solc_version('0.8.0')
filename = 'NodeRegistry.sol'

solidity_file_path = './solidity/' + filename

with open(solidity_file_path) as file:
    contract_source_code = file.read()

# 编译合约
compiled_sol = compile_source(contract_source_code, output_values=['abi', 'bin'])

# 提取合约名称（假设文件中只有一个合约）
contract_name = next(iter(compiled_sol)).split(':')[1]

contract_interface = compiled_sol[f'<stdin>:{contract_name}']
contract_abi = contract_interface['abi']
contract_bytecode = contract_interface['bin']

print(f"abi: {contract_abi}")

web3 = Web3(Web3.HTTPProvider('http://172.27.244.201:8545'))
web3.middleware_onion.inject(geth_poa_middleware, layer=0)
if not web3.is_connected():
    raise Exception('Failed to connect to the Ethereum node')

account = web3.eth.accounts[0]

Contract = web3.eth.contract(abi=contract_abi, bytecode=contract_bytecode)

tx_hash = Contract.constructor().transact({'from': account, 'nonce': web3.eth.get_transaction_count(account)})
tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)

contract_address = tx_receipt.contractAddress

print(f"contract address: {contract_address}")

# 创建Python文件名
python_filename = camel_to_snake(filename.replace('.sol', '')) + '.py'
python_file_path = './' + python_filename

# 将ABI中的false和true转换为False和True
abi_str = json.dumps(contract_abi)
abi_str = re.sub(r'\bfalse\b', 'False', abi_str)
abi_str = re.sub(r'\btrue\b', 'True', abi_str)

# 写入ABI和合约地址
with open(python_file_path, 'w') as py_file:
    py_file.write(f"ABI = {abi_str}\n")
    py_file.write(f"CONTRACT_ADDRESS = '{contract_address}'\n")

print(f"Created {python_file_path} with ABI and contract address")
